package brwarner.game 
{
	import flash.geom.Point;
	import assets.Assets;
	/**
	 * ...
	 * @author Brook Jensen
	 */
	public class Attacks 
	{
		//Gets a burst layer and adds it to an array
		public static function burstLayer( tile:Point, layer:Number, result:Array )
		{
			for ( var x = -layer; x <= layer; x++ )
			{
				for ( var y = -layer; y <= layer; y++ )
				{
					var p:Point = new Point( tile.x + x, tile.y + y );
					if ( !( p.x < 0 || p.y < 0 || p.x >= GameConstants.GRID_SIZE || p.y >= GameConstants.GRID_SIZE) )
						result.push(p);
				}
			}
		}
		
		//Burst helper function
		public static function burst( tile:Point, radius:Number )
		{
			var result:Array = new Array();
			for ( var i = 1; i <= radius; i++ ) burstLayer( tile, i, result );
			return result;
		}
		
		//Line helper function
		public static function line( tile:Point, direction:Number, length:Number ):Array
		{
			//Get direction vector
			var dirVec:Point = Direction.directionVector( direction );
			
			//Create result
			var result:Array = new Array();
			
			//Move in that direction
			var pos:Point = tile;
			for ( var i = 0; i < length; i++ )
			{
				//Add point
				result.push(pos);
				
				//Move and check
				pos = pos.add( dirVec );
				if ( pos.x < 0 || pos.y < 0 || pos.x > GameConstants.GRID_SIZE-1 || pos.y > GameConstants.GRID_SIZE-1 )
					break;
			}
			return result;
		}
		
		//Damage helper
		public static function damageGroup( group:Array, grid:GameGrid, damage:Number, damagePerCapita:Number )
		{
			//Damage the group
			group.forEach( function( e:Point, i:Number, a:Array ) {
				grid.getTile( e ).Damage( damage + damagePerCapita * grid.getTile( e ).Population );
			});
		}
		
		//Attack database
		public static const ATTACKS:Array = new Array(
		//{ type: GridSquare.RIVER, func: floodAttack, image: Assets.Avalanche, directional: false, fire: 0, water: 5, ground: 0, air: 0 },
		{ type: [GridSquare.SNOW_MOUNTAIN], damageFunc: avalancheAttack, areaFunc: avalancheArea, image: Assets.Avalanche, directional: true, fire: 0, water: 50, ground: 30, air: 0 },
		{ type: [GridSquare.PLAIN, GridSquare.FOREST], damageFunc: droughtAttack, areaFunc: droughtArea, image: Assets.Drought, directional: false, fire: 10, water: 0, ground: 10, air: 0 },
		{ type: [GridSquare.RIVER], damageFunc: floodAttack, areaFunc: floodArea, image: Assets.Flood, directional: false, fire: 0, water: 30, ground: 0, air: 0 },
		{ type: true, damageFunc: meteorAttack, areaFunc: meteorArea, image: Assets.Meteor, directional: false, fire: 150, water: 0, ground: 0, air: 0 }
		);
		
		private static function avalancheArea( tile:Point, grid:GameGrid, direction:Number ):Array
		{
			return line( tile, direction, 3 );
		}
		private static function avalancheAttack( tile:Point, grid:GameGrid, direction:Number):void
		{
			damageGroup( avalancheArea(tile, grid, direction), grid, 100, 0 );
		}
		
		private static function floodArea( tile:Point, grid:GameGrid ):Array
		{
			return burst(tile, 1);
		}
		private static function floodAttack( tile:Point, grid:GameGrid):void
		{
			var area:Array = floodArea(tile, grid);
			area.forEach( function( e:Point, i:Number, a:Array ) {
				if( !grid.getTile(e).Infected )
					grid.getTile(e).tempTypeChange( GridSquare.RIVER, 4*GameConstants.FRAME_RATE);
			});
			damageGroup( area, grid, 5, 0.2 );
		}
		
		private static function meteorArea( tile:Point, grid:GameGrid ):Array
		{
			return burst(tile, 1);
		}
		private static function meteorAttack( tile:Point, grid:GameGrid):void
		{
			var result:Array = new Array();
			burstLayer( tile, 1, result );
			damageGroup(  result, grid, 50, 0 );
			damageGroup( [ tile ], grid, 150, 0 );
		}
		
		private static function droughtArea( tile:Point, grid:GameGrid ):Array
		{
			var result:Array = new Array();
			result.push(tile);
			if ( tile.x > 0 ) result.push( new Point( tile.x - 1, tile.y) );
			if ( tile.y > 0 ) result.push( new Point( tile.x, tile.y - 1 ) );
			if ( tile.x < GameConstants.GRID_SIZE - 1 ) result.push( new Point( tile.x + 1, tile.y ) );
			if ( tile.y < GameConstants.GRID_SIZE - 1 ) result.push( new Point( tile.x, tile.y + 1 ) );
			return result;
		}
		private static function droughtAttack( tile:Point, grid:GameGrid):void
		{
			damageGroup( droughtArea(tile, grid), grid, 10, 0.1 );
		}
		
	}

}